package com.sq.imp.MyMenuManagers;

import com.sq.abstractClass.Text;

import javax.swing.*;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

public class FindReplaceManager {
    private final Text textArea;
    private Highlighter highlighter;
    private final Highlighter.HighlightPainter painter;
    private Pattern pattern;
    private Matcher matcher;
    private int lastMatchIndex;
    private final JFrame frame;

    public FindReplaceManager(Text textArea, JFrame frame) {
        this.textArea = textArea;
        this.highlighter = textArea.getHighlighter();
        this.painter = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
        this.frame = frame;
    }

    public void showFindDialog() {
        showFindReplaceDialog(true);
    }

    public void showReplaceDialog() {
        showFindReplaceDialog(false);
    }

    private void showFindReplaceDialog(boolean isFind) {
        final JDialog dialog = new JDialog(frame, isFind ? "查找" : "替换", false);
        dialog.setSize(400, isFind ? 300 : 350);
        dialog.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 5, 5);

        dialog.addWindowFocusListener(new WindowFocusListener() {
            @Override
            public void windowGainedFocus(WindowEvent e) {
            }

            @Override
            public void windowLostFocus(WindowEvent e) {
                dialog.dispose();
            }
        });

        final JTextField findField = new JTextField(20);
        final JTextField replaceField = isFind ? null : new JTextField(20);
        final JCheckBox caseSensitiveBox = new JCheckBox("区分大小写");
        final JCheckBox regexBox = new JCheckBox("使用正则表达式");
        final JCheckBox highlightAllBox = new JCheckBox("下一次高亮显示所有匹配项");
        JButton findNextButton = isFind ? new JButton("查找下一个") : null;
        JButton replaceNextButton = isFind ? null : new JButton("替换下一个");
        JButton replaceAllButton = isFind ? null : new JButton("替换所有");
        JButton clearHighlightsButton = new JButton("清除高亮");

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.EAST;
        dialog.add(new JLabel("查找："), gbc);

        gbc.gridx = 1;
        gbc.anchor = GridBagConstraints.WEST;
        dialog.add(findField, gbc);

        if (!isFind) {
            gbc.gridy++;
            gbc.anchor = GridBagConstraints.EAST;
            dialog.add(new JLabel("替换为："), gbc);

            gbc.anchor = GridBagConstraints.WEST;
            dialog.add(replaceField, gbc);
        }

        gbc.gridy++;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.WEST;
        dialog.add(caseSensitiveBox, gbc);

        gbc.gridy++;
        dialog.add(regexBox, gbc);

        gbc.gridy++;
        dialog.add(highlightAllBox, gbc);

        gbc.gridy++;
        gbc.gridwidth = 1;
        gbc.anchor = GridBagConstraints.CENTER;
        if (isFind) {
            dialog.add(findNextButton, gbc);
        } else {
            dialog.add(replaceNextButton, gbc);
        }
        gbc.gridy++;
        gbc.gridx = 1;
        if (isFind) {
            dialog.add(clearHighlightsButton, gbc);
        } else {
            dialog.add(replaceAllButton, gbc);
        }

        gbc.gridy++;
        gbc.gridx = 0;
        gbc.gridwidth = 2;

        ActionListener findAction = e -> performFind(findField.getText(), caseSensitiveBox.isSelected(), regexBox.isSelected(), highlightAllBox.isSelected());
        ActionListener replaceNextAction = e -> {
            if (replaceField != null) {
                performReplaceNext(findField.getText(), replaceField.getText(), caseSensitiveBox.isSelected(), regexBox.isSelected());
            }
        };
        ActionListener replaceAllAction = e -> {
            if (replaceField != null) {
                performReplaceAll(findField.getText(), replaceField.getText(), caseSensitiveBox.isSelected(), regexBox.isSelected());
            }
        };
        ActionListener clearHighlightsAction = e -> textArea.getHighlighter().removeAllHighlights();

        if (isFind) {
            findNextButton.addActionListener(findAction);
        } else {
            replaceNextButton.addActionListener(replaceNextAction);
            replaceAllButton.addActionListener(replaceAllAction);
        }
        clearHighlightsButton.addActionListener(clearHighlightsAction);
        dialog.setVisible(true);
    }

    private void performFind(String findStr, boolean caseSensitive, boolean useRegex, boolean highlightAll) {
        if (findStr == null || findStr.isEmpty()) {
            JOptionPane.showMessageDialog(frame, "请输入查找内容！", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        try {
            int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
            pattern = useRegex ? Pattern.compile(findStr, flags) : Pattern.compile(Pattern.quote(findStr), flags);
            matcher = pattern.matcher(textArea.getText());
            if (matcher.find(lastMatchIndex)) {
                int start = matcher.start();
                int end = matcher.end();
                textArea.setCaretPosition(start);
                textArea.moveCaretPosition(end);
                lastMatchIndex = end;

                if (highlightAll) {
                    highlightAllMatches(findStr, caseSensitive, useRegex);
                } else {
                    highlighter = textArea.getHighlighter();
                    textArea.getHighlighter().removeAllHighlights();
                    highlighter.addHighlight(start, end, painter);
                }
            } else {
                JOptionPane.showMessageDialog(frame, "未找到更多匹配项！", "查找结果", JOptionPane.INFORMATION_MESSAGE);
                lastMatchIndex = 0;
            }
        } catch (PatternSyntaxException e) {
            JOptionPane.showMessageDialog(frame, "无效的正则表达式！", "错误", JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(frame, "查找失败！", "错误", JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }

    private void highlightAllMatches(String findStr, boolean caseSensitive, boolean useRegex) {
        textArea.getHighlighter().removeAllHighlights();
        try {
            int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
            pattern = useRegex ? Pattern.compile(findStr, flags) : Pattern.compile(Pattern.quote(findStr), flags);
            matcher = pattern.matcher(textArea.getText());
            while (matcher.find()) {
                highlighter.addHighlight(matcher.start(), matcher.end(), painter);
            }
        } catch (PatternSyntaxException e) {
            JOptionPane.showMessageDialog(frame, "无效的正则表达式！", "错误", JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(frame, "高亮失败！", "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void performReplaceNext(String findStr, String replaceStr, boolean caseSensitive, boolean useRegex) {
        if (findStr == null || findStr.isEmpty()) {
            JOptionPane.showMessageDialog(frame, "请输入查找内容！", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        if (replaceStr == null || replaceStr.isEmpty()) {
            JOptionPane.showMessageDialog(frame, "请输入替换内容！", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        try {
            int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
            pattern = useRegex ? Pattern.compile(findStr, flags) : Pattern.compile(Pattern.quote(findStr), flags);
            matcher = pattern.matcher(textArea.getText());
            if (matcher.find(lastMatchIndex)) {
                int start = matcher.start();
                int end = matcher.end();
                String newContent = textArea.getText().substring(0, start) + replaceStr + textArea.getText().substring(end);
                textArea.setText(newContent);
                lastMatchIndex = start + replaceStr.length();
                textArea.getHighlighter().removeAllHighlights();
                highlighter.addHighlight(start, lastMatchIndex, painter);
            } else {
                JOptionPane.showMessageDialog(frame, "未找到更多匹配项！", "替换结果", JOptionPane.INFORMATION_MESSAGE);
                lastMatchIndex = 0;
            }
        } catch (PatternSyntaxException e) {
            JOptionPane.showMessageDialog(frame, "无效的正则表达式！", "错误", JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(frame, "替换失败！", "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void performReplaceAll(String findStr, String replaceStr, boolean caseSensitive, boolean useRegex) {
        if (findStr == null || findStr.isEmpty()) {
            JOptionPane.showMessageDialog(frame, "请输入查找内容！", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        if (replaceStr == null || replaceStr.isEmpty()) {
            JOptionPane.showMessageDialog(frame, "请输入替换内容！", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        try {
            int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
            pattern = useRegex ? Pattern.compile(findStr, flags) : Pattern.compile(Pattern.quote(findStr), flags);
            String newContent = pattern.matcher(textArea.getText()).replaceAll(replaceStr);
            textArea.setText(newContent);
            textArea.getHighlighter().removeAllHighlights();
            lastMatchIndex = 0;
        } catch (PatternSyntaxException e) {
            JOptionPane.showMessageDialog(frame, "无效的正则表达式！", "错误", JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(frame, "替换失败！", "错误", JOptionPane.ERROR_MESSAGE);
        }
    }
}